package c.c.d.s.s.o.c.as.configuration;

import c.c.d.s.s.o.c.as.configuration.support.user.UsernamePasswordAuthenticationProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;

/**
 * Security 配置
 *
 * @author LiKe
 * @version 1.0.0
 * @date 2020-06-15 09:41
 */
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    /**
     * 默认的登陆端点
     */
    public static final String DEFAULT_LOGIN_URL = "/login";

    // ~ AuthenticationManagerBuilder
    // -----------------------------------------------------------------------------------------------------------------

    /**
     * {@link UsernamePasswordAuthenticationProvider}
     */
    private AuthenticationProvider authenticationProvider;

    // =================================================================================================================

    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(authenticationProvider);
    }

    @Override
    public void configure(WebSecurity web) {
        // web.securityInterceptor();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        // ~ 授权服务器不需要开启 CSRF: 为客户端
        http.csrf().disable();

        // ~ Authorization Code Grant 和 Implicit Grant 需要开启表单登陆
        http.formLogin().and().addFilter(defaultLoginPageGeneratingFilter());

        // ~ 禁用 Authorization: Basic xxx
        http.httpBasic().disable();

        http.authorizeRequests().anyRequest().authenticated();
        // @formatter:on
    }

    /**
     * Description: 用默认的登陆界面生成过滤器生成默认的登陆界面 /login.<br>
     * Details: 如果使用了自定义的 {@link AuthenticationEntryPoint}, {@link DefaultLoginPageGeneratingFilter} 就不会被配置, 所以这里需要手动配置.
     *
     * @see DefaultLoginPageGeneratingFilter
     * @see org.springframework.security.config.annotation.web.configurers.DefaultLoginPageConfigurer
     */
    private DefaultLoginPageGeneratingFilter defaultLoginPageGeneratingFilter() {
        final DefaultLoginPageGeneratingFilter defaultLoginPageGeneratingFilter = new DefaultLoginPageGeneratingFilter(new UsernamePasswordAuthenticationFilter());
        defaultLoginPageGeneratingFilter.setAuthenticationUrl(DEFAULT_LOGIN_URL);
        return defaultLoginPageGeneratingFilter;
    }

    // ~ Bean
    // -----------------------------------------------------------------------------------------------------------------

    @Bean
    public AuthenticationManager defaultAuthenticationManager() throws Exception {
        return authenticationManager();
    }

    // ~ Autowired
    // -----------------------------------------------------------------------------------------------------------------

    @Autowired
    public void setAuthenticationProvider(@Qualifier("usernamePasswordAuthenticationProvider") AuthenticationProvider authenticationProvider) {
        this.authenticationProvider = authenticationProvider;
    }

}
